/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../data_struct/head.h"
#include "curl_impl.h"
#include "mgr.h"

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 

namespace xos_curl
{
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    static curl_impl::ITEM_DATA xos_item_data;

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    curl_impl::curl_impl()
    {
        m_pSlist = 0;
        m_pCurl = 0;
    }

    curl_impl::~curl_impl()
    {
        term();
    }

    /////////////////////////////////////////////////////////////////////////////////////////////
    // public method

    int curl_impl::get_xos_item_data( ITEM_DATA*& item_ptr )
    {
        int ret = 0;
        xos_item_data.set_container( mgr::container() );
        item_ptr = &xos_item_data;
        return ret;
    }

    int curl_impl::init()
    {
        int nResult = 0;
        int nRet = 0;

        if( 0 == nRet )
        {
            if( m_pCurl )
            {
                curl_easy_reset( m_pCurl );
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            m_pCurl = curl_easy_init();

            if( !m_pCurl )
            {
                nResult = 1;
                nRet = 1;
            }
        }

        return nResult;
    }

    int curl_impl::term()
    {
        int nRet = 0;

        if( m_pSlist )
        {
            curl_slist_free_all( m_pSlist );
            m_pSlist = 0;
        }

        if( m_pCurl )
        {
            curl_easy_cleanup( m_pCurl );
            m_pCurl = 0;
        }

        return nRet;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////
    // i_curl method

    int curl_impl::set_opt( int enumOpt, ... )
    {
        int nRet = 0;

        switch( enumOpt )
        {
        case OS_CURLOPT_URL:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_URL, va_arg( va, const char * ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_HEADERFUNCTION:
            {
                typedef size_t ( * F )( void * ptr, size_t size, size_t nmemb, void * stream );
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_HEADERFUNCTION, va_arg( va, F ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_HEADERDATA:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_HEADERDATA, va_arg( va, void * ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_WRITEFUNCTION:
            {
                typedef size_t ( * F )( void * ptr, size_t size, size_t nmemb, void * stream );
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_WRITEFUNCTION, va_arg( va, F ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_WRITEDATA:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_WRITEDATA, va_arg( va, void * ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_READFUNCTION:
            {
                typedef size_t ( * F )( void * ptr, size_t size, size_t nmemb, void * stream );
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_READFUNCTION, va_arg( va, F ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_READDATA:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_READDATA, va_arg( va, void * ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_NOPROGRESS:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_NOPROGRESS, va_arg( va, int ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_NOSIGNAL:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_NOSIGNAL, va_arg( va, long ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_PROGRESSFUNCTION:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_PROGRESSFUNCTION, va_arg( va, curl_progress_callback ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_PROGRESSDATA:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_PROGRESSDATA, va_arg( va, void * ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_CONNECTTIMEOUT_MS:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_CONNECTTIMEOUT_MS, va_arg( va, long ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_CONNECTTIMEOUT:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_CONNECTTIMEOUT, va_arg( va, long ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_TIMEOUT_MS:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_TIMEOUT_MS, va_arg( va, long ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_TIMEOUT:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_TIMEOUT, va_arg( va, long ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_FOLLOWLOCATION:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_FOLLOWLOCATION, va_arg( va, long ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_RANGE:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_RANGE, va_arg( va, char * ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_RESUME_FROM:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_RESUME_FROM, va_arg( va, long ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_ERRORBUFFER:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_ERRORBUFFER, va_arg( va, char * ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_UPLOAD:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_UPLOAD, va_arg( va, long ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_INFILESIZE_LARGE:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_INFILESIZE_LARGE, ( curl_off_t )( va_arg( va, double ) ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_POSTFIELDSIZE_LARGE:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_POSTFIELDSIZE_LARGE, ( curl_off_t )( va_arg( va, double ) ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_POST:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_POST, va_arg( va, long ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_HTTPHEADER:
            {
                va_list va;
                va_start( va, enumOpt );
                m_pSlist = curl_slist_append( m_pSlist, va_arg( va, const char * ) );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_HTTPHEADER, m_pSlist );
                va_end( va );
            }
            break;
        case OS_CURLOPT_POSTFIELDSIZE:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_POSTFIELDSIZE, va_arg( va, long ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_POSTFIELDS:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_POSTFIELDS, va_arg( va, const char * ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_MAX_SEND_SPEED_LARGE:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_MAX_SEND_SPEED_LARGE, va_arg( va, long ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_MAX_RECV_SPEED_LARGE:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_MAX_RECV_SPEED_LARGE, va_arg( va, long ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_LOW_SPEED_LIMIT:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_LOW_SPEED_LIMIT, va_arg( va, long ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_LOW_SPEED_TIME:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_LOW_SPEED_TIME, va_arg( va, long ) );
                va_end( va );
            }
            break;
            // 
            // cokie session
            // 
        case OS_CURLOPT_COOKIESESSION:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_COOKIESESSION, va_arg( va, long ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_COOKIELIST:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_COOKIELIST, va_arg( va, const char * ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_COOKIEFILE:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_COOKIEFILE, va_arg( va, const char * ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_COOKIEJAR:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_COOKIEJAR, va_arg( va, const char * ) );
                va_end( va );
            }
            break;
        case OS_CURLOPT_COOKIE:
            {
                va_list va;
                va_start( va, enumOpt );
                nRet = curl_easy_setopt( m_pCurl, CURLOPT_COOKIE, va_arg( va, const char * ) );
                va_end( va );
            }
            break;
        default:
            {
                nRet = 1;
            }
            break;
        }

        return nRet;
    }

    // 
    // 退出curl的读取函数
    // 
    int curl_impl::get_quit_read_code()
    {
        return ( int )CURL_READFUNC_ABORT;
    }

    // 
    // reset
    // 
    int curl_impl::reset()
    {
        int nRet = 0;

        if( m_pCurl )
        {
            curl_easy_reset( m_pCurl );
        }

        return nRet;
    }

    int curl_impl::perform()
    {
        int nRet = 0;

        nRet = curl_easy_perform( m_pCurl );

        if( m_pSlist )
        {
            curl_slist_free_all( m_pSlist );
            m_pSlist = 0;
        }

        if( CURLE_OK == nRet )
        {
            nRet = 0;
        }
        else
        {
            nRet = 1;
        }

        return nRet;
    }

    // 
    // 退出http(或其它协议)返回码
    // 
    int curl_impl::get_ret_code()
    {
        int nRet = 0;

        long lRet = 0;
        curl_easy_getinfo( m_pCurl, CURLINFO_RESPONSE_CODE, &lRet );
        nRet = ( int )lRet;

        return nRet;
    }

} // xos_curl
